package net.dirox.confluence.plugin.dao.service;

import static com.google.common.collect.Lists.newArrayList;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import net.dirox.confluence.plugin.ao.entities.Note;
import net.dirox.confluence.plugin.ao.entities.TaggedUser;
import net.dirox.confluence.plugin.ao.entities.User;
import net.java.ao.Query;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.atlassian.activeobjects.external.ActiveObjects;
import com.atlassian.sal.api.ApplicationProperties;
import com.atlassian.sal.api.user.UserManager;
import com.atlassian.sal.api.user.UserProfile;
import com.google.common.collect.ImmutableMap;

//import com.atlassian.crowd.embedded.api.User;

public class NoteServiceImpl implements NoteService {

	private final ActiveObjects ao;
	private final UserManager salUserManager;
	// private final ActivityService activityService;
	// private final JiraAuthenticationContext context;
	private final ApplicationProperties applicationProperties;
	private static final Logger log = LoggerFactory
			.getLogger(NoteServiceImpl.class);

	public NoteServiceImpl(ActiveObjects ao, UserManager salUserManager,
			ApplicationProperties applicationProperties) {
		super();
		this.ao = ao;
		this.salUserManager = salUserManager;
		this.applicationProperties = applicationProperties;
	}

	@Override
	public Note add(String content, int priority) {
		// TODO Auto-generated method stub

		User owner = currentUser();
		final Note note = ao.create(Note.class, ImmutableMap
				.<String, Object> of("OWNER_ID", owner, "CREATED_DATE",
						new Date(), "STATUS", true));
		note.setContent(content);
		note.setPriority(priority);
		note.save();

		return note;
	}

	@Override
	public Note update(int id, String content, int priority) {
		// TODO Auto-generated method stub
		Note note = ao.get(Note.class, id);
		String oldContent = note.getContent();
		note.setContent(content);
		if (priority != -1) {
			note.setPriority(priority);
		}
		note.save();
		return note;
	}

	@Override
	public void delete(int id) {
		// TODO Auto-generated method stub
		Note note = ao.get(Note.class, id);
		note.setStatus(false);
		note.save();
	}

	@Override
	public Note getNote(int id) {
		// TODO Auto-generated method stub
		return ao.get(Note.class, id);
	}

	@Override
	public List<Note> getAll() {
		// TODO Auto-generated method stub
		return newArrayList(ao.find(Note.class,
				Query.select().where("STATUS = ?", Note.STATUS_IN_USE)));
	}

	@Override
	public List<Note> getNotes(int priority) {
		// TODO Auto-generated method stub
		if (priority == -1)
			return newArrayList(ao.find(
					Note.class,
					Query.select().where("OWNER_ID = ? AND STATUS = ?",
							currentUser(), Note.STATUS_IN_USE)));
		return newArrayList(ao.find(
				Note.class,
				Query.select().where(
						"OWNER_ID = ? AND STATUS = ? AND PRIORITY = ?",
						currentUser(), Note.STATUS_IN_USE, priority)));
	}

	@Override
	public List<Note> getMemos() {
		// TODO Auto-generated method stub
		User currUser = currentUser();
		List<Note> memos = new ArrayList<Note>();
		for (Note note : getAll()) {
			for (User user : note.getUsers()) {
				if (user.getUserName().equals(currUser.getUserName())) {
					memos.add(note);
				}
			}
		}
		return memos;
	}

	@Override
	public void tagNoteToUser(Note note,
			com.atlassian.crowd.embedded.api.User user) {
		// TODO Auto-generated method stub
		User u = getOrCreateUser(user.getName(), user.getDisplayName());
		final TaggedUser taggedUser = ao.create(TaggedUser.class);
		taggedUser.setNote(note);
		taggedUser.setUser(u);
		taggedUser.save();
	}

	@Override
	public void untagNoteToUser(Note note,
			net.dirox.confluence.plugin.ao.entities.User user) {
		TaggedUser[] taggedUsers = ao.find(TaggedUser.class, Query.select()
				.where("NOTE_ID = ? AND USER_ID = ?", note, user));
		if (taggedUsers.length > 0) {
			ao.delete(taggedUsers[0]);
		}
	}

	@Override
	public void associateUsers(Note note,
			com.atlassian.crowd.embedded.api.User[] arrUsers) {
		// TODO Auto-generated method stub
		boolean isDuplicated = false;
		User[] old_users = note.getUsers();
		for (User u : old_users) {
			isDuplicated = false;
			for (com.atlassian.crowd.embedded.api.User user : arrUsers) {
				if (u.getUserName().equals(user.getName())) {
					isDuplicated = true;
					break;
				}
			}
			// untagged user from note
			if (isDuplicated == false) {
				untagNoteToUser(note, u);
			}
		}

		for (com.atlassian.crowd.embedded.api.User user : arrUsers) {
			isDuplicated = false;
			for (User u : old_users) {
				if (u.getUserName().equals(user.getName())) {
					isDuplicated = true;
					break;
				}
			}
			// tagged user from note
			if (isDuplicated == false) {
				tagNoteToUser(note, user);
			}
		}
	}

	@Override
	public User currentUser() {
		UserProfile profile = salUserManager.getUserProfile(salUserManager
				.getRemoteUsername());

		return getOrCreateUser(profile.getUsername(), profile.getFullName());
	}

	private User getOrCreateUser(String userName, String displayName) {
		User[] users = ao.find(User.class,
				Query.select().where("USER_NAME = ?", userName));
		if (users.length == 0) {
			return createUser(userName, displayName);
		} else if (users.length == 1) {
			// update user
			users[0].setDisplayName(displayName);
			users[0].save();

			return users[0];
		} else {
			throw new IllegalStateException(
					"Found multiple users for username: " + userName);
		}
	}

	private User createUser(String userName, String displayName) {
		return ao.create(User.class, ImmutableMap.<String, Object> of(
				"USER_NAME", userName, "DISPLAY_NAME", displayName));
	}

}
